/**
 * @file filter
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  PureComponent,
  PropTypes
} from 'react';
import {render} from '../../renderer';
import * as cx from 'classnames';
import * as assign from 'object-assign';
import * as omit from 'lodash/omit';
import {confirm} from '../../../widgets/alert/alert';
import {Enhance as FormItem} from '../form-item';

let dom;
const stripTag = value => {
  if (!value) {
    return value;
  }
  dom = dom || document.createElement('div');
  dom.innerHTML = value;
  return dom.innerText;
};

@FormItem({
  type: 'form',
  test: (path, config) => /(?:^|\/)form-item$/.test(path) && config.type === 'form' && config.form && !config.forms,
  validateSchema: 'http://amis.baidu.com/schemas/form.json#/definitions/formItem'
})
export default class FormSubForm extends PureComponent {
  static propTypes = {
    className: PropTypes.string,
    formMode: PropTypes.string,
    formHorizontal: PropTypes.object,
    inputClassName: PropTypes.string,
    onRequestAction: PropTypes.func,
    form: PropTypes.object.isRequired,
    multiple: PropTypes.bool
  };

  static defaultProps = {
    value: '',
    inlineLabelClassName: '',
    btnLabel: '设置',
    btnClassName: 'btn-info',
    multiple: false,
    labelField: 'label',
    addable: true,
    removable: true,
    maxLength: 0
  };

  values = {};

  constructor(props) {
    super(props);

    this.openSubForm = this.openSubForm.bind(this);
    this.addForm = this.addForm.bind(this);
    this.removeForm = this.removeForm.bind(this);
    this.handleFormResolved = this.handleFormResolved.bind(this);
    this.close = this.close.bind(this);
    const dialogSchema = this.buildSchema(props);

    this.state = {
      openedIndex: -1,
      dialogSchema
    };
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;

    if (props.form !== nextProps.form) {
      this.setState({
        dialogSchema: this.buildSchema(nextProps)
      });
    }
  }

  openSubForm(index = 0) {
    this.setState({
      openedIndex: index
    });
    return false;
  }

  addForm() {
    let value = (this.props.getValue() || []).concat();

    if (!Array.isArray(value)) {
      value = [value];
    }

    const labelField = this.props.labelField;

    value.push({
      [labelField]: ''
    });

    this.props.setValue(value);
  }

  removeForm(index) {
    let value = (this.props.getValue() || []).concat();

    if (!Array.isArray(value)) {
      value = [value];
    }

    if (value[index]) {
      value.splice(index, 1);
    }

    this.props.setValue(value);
  }

  handleFormResolved(values) {
    const {
      multiple
    } = this.props;

    if (multiple) {
      let value = this.props.getValue() || [];
      if (!Array.isArray(value)) {
        value = [value];
      }

      value = value.concat();
      value[this.state.openedIndex] = assign({}, value[this.state.openedIndex], values);
      this.props.setValue(value);
    } else {
      this.props.setValue(values);
    }

    this.values[this.state.openedIndex] = values;
    this.close();
  }

  close() {
    this.setState({
      openedIndex: -1
    });
  }

  buildSchema(props) {
    const form = props.form;

    if (!form) {
      return null;
    }

    const basicForm = omit(form, ['title', 'actions', 'name']);
    const {
      size
    } = this.props;

    return {
      title: form.title,
      name: form.name,
      size,
      body: assign(basicForm, {
        type: 'basic-form'
      })
    }
  }

  renderInput() {
    const {
      btnLabel,
      btnClassName,
      multiple,
      labelField,
      disabled,
      addable,
      removable,
      maxLength
    } = this.props;

    let value = this.props.getValue()

    if (multiple) {
      value = value || [];
      if (!Array.isArray(value)) {
        value = [value];
      }
      const doms = [];
      value.forEach((item, key) => {
        doms.push(
          <button
            type="button"
            key={key}
            onClick={this.openSubForm.bind(this, key)}
            className="btn btn-sm m-b-xs m-r-xs btn-info btn-addon"
          >
            {item[labelField] && stripTag(item[labelField]) || btnLabel}
            {disabled || !removable ? null : (<i
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();

                confirm('确定要删除?').then(() => this.removeForm(key));
                return false;
              }}
              className="fa fa-times"
            />)}
          </button>
        )
      });

      addable && (!maxLength || value.length < maxLength) && doms.push(
        <button
          type="button"
          key="add-more"
          className="btn btn-default btn-sm rounded m-b-xs m-r-xs"
          onClick={this.addForm}
          disabled={disabled}
        >
          <i className="fa fa-plus" />
        </button>
      );

      return doms;
    }

    return (
      <button
        type="button"
        className={cx('btn btn-addon btn-sm', btnClassName)}
        onClick={this.openSubForm}
        disabled={disabled}
      >
        {value && value[labelField] && stripTag(value[labelField])|| btnLabel}
        <i className="fa fa-cog" />
      </button>
    )
  }

  render() {
    const {
      $path,
      locals,
      name,
      disabled,
      multiple
    } = this.props;

    let body = <div key="input">{this.renderInput()}</div>;


    const {openedIndex, dialogSchema} = this.state;
    const value = this.props.getValue();

    return (
      <div>
        {body}
        {openedIndex !== -1 && dialogSchema ? render(`${$path}/form-dialog`, dialogSchema, {
          key: openedIndex,
          data: assign({}, (multiple ? value && value[openedIndex] : value) || this.values[openedIndex] || {}),
          name: `${name}-${dialogSchema.name || 'sub-form'}`,
          locals: locals,
          onClose: this.close,
          onResolved: this.handleFormResolved,
          disabled
        }) : null}
      </div>
    );
  }
}
